/*
 * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.pneditor.petrinet;

import java.util.Collection;

/**
 *
 * @author Martin Riesz <riesz.martin at gmail.com>
 */
public class NodeLabelGenerator {
	
	private int nextUniquePlaceNumber = 1;
	private int nextUniqueTransitionNumber = 1;
	private int nextUniqueSubnetNumber = 1;
	private PetriNet petriNet;

	public NodeLabelGenerator(PetriNet petriNet) {
		this.petriNet = petriNet;
	}
	
	private void setUniqueLabel(Node node) {
		String label;
		if (node instanceof Place) {
			label = getPrefix(node) + Integer.toString(nextUniquePlaceNumber++);
		}
		else if (node instanceof Transition) {
			label = getPrefix(node) + Integer.toString(nextUniqueTransitionNumber++);
		}
		else if (node instanceof Subnet) {
			label = getPrefix(node) + Integer.toString(nextUniqueSubnetNumber++);
		}
		else if (node instanceof ReferencePlace) {
			throw new RuntimeException("Why would anyone want to label a ReferencePlace?");
		}
		else {
			throw new RuntimeException("Node which is neither Place nor Transition nor Subnet nor ReferencePlace.");
		}
		node.setLabel(label);
	}
	
	private String getPrefix(Node node) {
		String prefix;
		if (node instanceof Place) {
			prefix = "p";
		}
		else if (node instanceof Transition) {
			prefix = "t";
		}
		else if (node instanceof Subnet) {
			prefix = "s";
		}
		else if (node instanceof ReferencePlace) {
			throw new RuntimeException("Why would anyone want to label a ReferencePlace?");
		}
		else {
			throw new RuntimeException("Node which is neither Place nor Transition nor Subnet nor ReferencePlace.");
		}
		return prefix;
	}

	public void setLabelToNewlyCreatedNode(Node node) {
//		setUniqueLabel(node);
	}

	public void setLabelsToPastedContent(Collection<Element> elements) {
		for (Element element : elements) {
			if (element instanceof Node && !(element instanceof ReferencePlace) ) {
//				setUniqueLabel((Node)element);
			}
		}
	}

	public void setLabelsToReplacedSubnet(Subnet subnet) {
		for (Node node : subnet.getNodesRecursively()) {
			if (!(node instanceof ReferencePlace)) {
//				if (isNodeAutolabeled(node)) {
//					setUniqueLabel(node);
//				}
			}
		}
	}

	public void setLabelsOfConversionTransitionToSubnet(Transition transition, Subnet subnet) {
//		if (isNodeAutolabeled(transition)) {
//			setUniqueLabel(subnet);
//		}
//		else {
//			subnet.setLabel(transition.getLabel());
//			setUniqueLabel(transition);
//		}
		
		subnet.setLabel(transition.getLabel());
		transition.setLabel(null);
	}
	
	public void cloneLabel(Node newNode, Node oldNode) {
//		if (isNodeAutolabeled(oldNode)) {
//			setUniqueLabel(newNode);
//		}
//		else {
			newNode.setLabel(oldNode.getLabel());
//		}
	}

	private boolean isNodeAutolabeled(Node node) {
		return node.getLabel().matches("^" + getPrefix(node) + "[0-9]+$");
	}

	public void fixFutureUniqueLabels() {
		int maxPlaceNumber = 0;
		int maxTransitionNumber = 0;
		int maxSubnetNumber = 0;
		
		for (Place place : petriNet.getRootSubnet().getPlacesRecursively()) {
			String placeLabel = place.getLabel();
			if (placeLabel != null && placeLabel.startsWith(getPrefix(place))) {
				try {
					int placeNumber = Integer.parseInt(placeLabel.substring(1));
					if (placeNumber > maxPlaceNumber) {
						maxPlaceNumber = placeNumber;
					}
				}
				catch (NumberFormatException ex) {
					//do nothing
				}
			}
		}
		for (Transition transition : petriNet.getRootSubnet().getTransitionsRecursively()) {
			String transitionLabel = transition.getLabel();
			if (transitionLabel != null && transitionLabel.startsWith(getPrefix(transition))) {
				try {
					int transitionNumber = Integer.parseInt(transitionLabel.substring(1));
					if (transitionNumber > maxTransitionNumber) {
						maxTransitionNumber = transitionNumber;
					}
				}
				catch (NumberFormatException ex) {
					//do nothing
				}
			}
		}
		for (Subnet subnet : petriNet.getRootSubnet().getSubnetsRecursively()) {
			String subnetLabel = subnet.getLabel();
			if (subnetLabel != null && subnetLabel.startsWith(getPrefix(subnet))) {
				try {
					int subnetNumber = Integer.parseInt(subnetLabel.substring(1));
					if (subnetNumber > maxSubnetNumber) {
						maxSubnetNumber = subnetNumber;
					}
				}
				catch (NumberFormatException ex) {
					//do nothing
				}
			}
		}
		nextUniquePlaceNumber = maxPlaceNumber + 1;
		nextUniqueTransitionNumber = maxTransitionNumber + 1;
		nextUniqueSubnetNumber = maxSubnetNumber + 1;
	}
}
